home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / util / libs / MMULib.lha / MMULib / Lib_Sources / mu_lib.asm < prev    next >
Encoding:
Assembly Source File  |  1998-10-04  |  20.9 KB  |  633 lines

  1. ;*************************************************************************
  2. ;** mmu.library                                                         **
  3. ;**                                                                     **
  4. ;** a system library for arbitration and control of the MC68K MMUs      **
  5. ;**                                                                     **
  6. ;** © 1998 THOR-Software, Thomas Richter                                **
  7. ;** No commercial use, reassembly, modification without prior, written  **
  8. ;** permission of the authors.                                          **
  9. ;** Including this library in any commercial software REQUIRES a        **
  10. ;** written permission and the payment of a small fee.                  **
  11. ;**                                                                     **
  12. ;** This is an internal header file, do not depend on anything here.    **
  13. ;** Use the official include files.                                     **
  14. ;** Distributed only for the mmu.library development group for private  **
  15. ;** use.                                                                **
  16. ;**                                                                     **
  17. ;**---------------------------------------------------------------------**
  18. ;** Block: The library base                                             **
  19. ;** Initializisation and basic jump vectors of the mmu.library          **
  20. ;*************************************************************************
  21.  
  22. ;FOLD Includes
  23.         include INC:macros.asm
  24.         include mu_lib.i
  25.         include mu_version.i
  26.         include mu_alerts.i
  27.         include mu_context.i
  28.         include kaputstr.i
  29.  
  30. ;we include just the offsets.
  31. ;I personally hate to write _LVO all the time, this is stripped
  32. ;in this file.
  33.         include INC:exec_lib.asm
  34. ;ENDFOLD
  35. ;FOLD External References
  36.         xref DetectMMUType
  37.         xref AllocAligned
  38.         xref MUCreatePool
  39.         xref MUDeletePool
  40.         xref AllocContext
  41.         xref BuildDefaultTable
  42.         xref LockContext
  43.         xref UnlockContext
  44.         xref AllocContextMem
  45.         xref FreeContextMem
  46.         xref FreeContext
  47.         xref SetGlobal
  48.         xref BuildMMUTable
  49.         xref ParseMMUTable
  50.  
  51.         xref Init851
  52.         xref Init030
  53.         xref Init040
  54.         xref Init060
  55. ;ENDFOLD
  56. ;FOLD Defines
  57. ;I'm again too lazy to include the complete exec/execbase.i.
  58. ;Here just what I need:
  59. AttnFlags       =       $128
  60. ;ENDFOLD
  61.  
  62.         section main_code,code
  63.  
  64. ;FOLD DOS Entry
  65. ;*************************************************
  66. ;** DOS Entry                                   **
  67. ;** Since this is not supposed to be executable,**
  68. ;** we return -1. This is an indicator for the  **
  69. ;** shell not to execute it.                    **
  70. ;*************************************************
  71. DosEntry:
  72.         moveq #-1,d0
  73.         rts
  74. ;ENDFOLD
  75. ;FOLD Resident
  76. ;*************************************************
  77. ;** Resident                                    **
  78. ;** the resident structure of this library      **
  79. ;** used for the autoinit function              **
  80. ;*************************************************
  81. Resident:
  82.         dc.w $4afc                      ;MatchWord
  83.         dc.l Resident                   ;Back pointer
  84.         dc.l 0                          ;no endskip
  85.         dc.b $80                        ;add to the system, do not jump in
  86.         dc.b Version                    ;version nummer
  87.         dc.b NT_LIBRARY                 ;this is a library
  88.         dc.b 0                          ;priority
  89.         dc.l MMUName                    ;name of the library
  90.         dc.l IDString                   ;ID string
  91.         dc.l Init                       ;pointer to the init data
  92.  
  93.         section main_data,data          ;we continue in the data
  94.                                         ;segment for consitency
  95. Init:
  96.         dc.l mulib_len                  ;size of the library
  97.         dc.l FuncInit                   ;jump vector init data, below
  98.         dc.l 0                          ;no structinit. I can't stand this mess
  99.         dc.l LibInit                    ;library init vector
  100. ;ENDFOLD
  101. ;FOLD FuncInit
  102. ;*************************************************
  103. ;** FuncInit                                    **
  104. ;** Library jump vector inits                   **
  105. ;*************************************************
  106. FuncInit:
  107.         dc.l OpenMULib
  108.         dc.l CloseMULib
  109.         dc.l ExpungeMULib
  110.         dc.l ExtFunc                    ;Extended function, unused
  111.  
  112.                                         ;Library functions follow here
  113.         dc.l AllocAligned
  114.         dc.l GetMapping
  115.         dc.l ReleaseMapping
  116.         dc.l GetPageSize
  117.         dc.l GetMMUType
  118.  
  119.         dc.l GetMMUConfig
  120.         dc.l ReleaseMMUConfig
  121.  
  122.         dc.l -1
  123. ;ENDFOLD
  124.  
  125.         section main_code,code
  126.  
  127. ;FOLD Stub routines, reserved routines etc.
  128.         opt c+
  129.         xdef ___stub
  130. ___stub:
  131.         opt c-
  132. ExtFunc:
  133. ReservedVector:
  134.         moveq #0,d0
  135.         rts
  136. ;ENDFOLD
  137.  
  138. ;FOLD MUAlert
  139. ;*************************************************
  140. ;** Alert routine                               **
  141. ;** Alerts with the alert ID on the stack       **
  142. ;** this long word is removed automagically     **
  143. ;*************************************************
  144.         xdef MUAlert
  145. MUAlert:
  146.         saveregs d0-d1/d7/a0-a1/a5-a6
  147.         move.l $20(a7),d7                       ;get alert code
  148.         move.l mulib_CurrentContext(a6),a5      ;this as parameter
  149.         move.l mulib_SysBase(a6),a6
  150.         jsr Alert(a6)
  151.         loadregs
  152.         move.l (a7)+,(a7)
  153.         rts
  154. ;ENDFOLD
  155.  
  156. ;FOLD LibInit
  157. ;*************************************************
  158. ;** LibInit                                     **
  159. ;** the Library Init vector                     **
  160. ;** we're called like this:                     **
  161. ;** Library base in d0, ExecBase in a6          **
  162. ;** BPTR segment in a0                          **
  163. ;**                                             **
  164. ;** We must return the initialized library base **
  165. ;** in d0, or NULL in case of a failure         **
  166. ;*************************************************
  167. LibInit:
  168.         saveregs d2/a4/a6
  169.  
  170.         move.l d0,a4
  171.  
  172.         kaputstr <"Library base is %lx, ExecBase is %lx">,a4,a6
  173.  
  174.         move.l a6,mulib_SysBase(a4)             ;keep SysBase
  175.         move.l a0,mulib_Segment(a4)
  176.         move.b 1+AttnFlags(a6),mulib_AttnFlags(a4)  ;copy AttnFlags
  177.  
  178.         move.b #NT_LIBRARY,mulib_type(a4)       ;type is library
  179.         move.b #(1<<lib_changed)!(1<<lib_sumused),mulib_flags(a4)       ;library flags
  180.         move.l #MMUName,mulib_name(a4)
  181.         move.l #IDString,mulib_idstring(a4)
  182.         move.l #PackedVersion,mulib_version(a4) ;Version, Revision at once
  183.  
  184.         lea mulib_ContextList(a4),a0
  185.         NewList a0                              ;initialize the context list    
  186.  
  187.                                                 ;initialize the semaphores
  188.         lea mulib_ContextSemaphore(a4),a0
  189.         jsr InitSemaphore(a6)
  190.         lea mulib_PoolSemaphore(a4),a0
  191.         jsr InitSemaphore(a6)
  192.  
  193.         btst #AF_68040,mulib_AttnFlags(a4)      ;no need to bother ramlib
  194.         beq.s .donttry
  195.  
  196.         lea MC68040Name,a1
  197.         moveq #0,d0
  198.         jsr OpenLibrary(a6)
  199.         move.l d0,mulib_040Base(a4)
  200.  
  201.         lea MC68060Name,a1
  202.         moveq #0,d0
  203.         jsr OpenLibrary(a6)
  204.         move.l d0,mulib_060Base(a4)
  205.  
  206. .donttry:
  207.         lea ExpansionName,a1
  208.         moveq #37,d0
  209.         jsr OpenLibrary(a6)
  210.         move.l d0,mulib_ExpansionBase(a4)
  211.         beq .noexpansion
  212.  
  213.         lea UtilityName,a1
  214.         moveq #37,d0                            ;Version 37 minimum
  215.         jsr OpenLibrary(a6)
  216.         move.l d0,mulib_UtilityBase(a4)
  217.         beq .noutility                          ;exit on failure
  218.  
  219.         move.l a4,a6
  220.  
  221.         move.l #$1,d0                           ;MEMF_PUBLIC
  222.         move.l #(map_len+4)*32,d1               ;puddle size related to mapping structures
  223.         move.l #(map_len+4)*4,d2                ;puddle threshold
  224.         bsr MUCreatePool                        ;create the memory pool
  225.         move.l d0,mulib_ContextPool(a4)
  226.         beq .nomemory
  227.  
  228.         bsr DetectMMUType                       ;read MMU type
  229.         ifd fake040
  230.          moveq #mutype_68040,d0
  231.         endc
  232.         ifd fake060
  233.          moveq #mutype_68060,d0
  234.         endc
  235.         move.b d0,mulib_MMUType(a4)
  236.  
  237.         lea NOP(pc),a0
  238.         lea mulib_Internals(a4),a1
  239.         for.l #mulib_InternalVecs,d1
  240.          move.w #$4ef9,(a1)+                    ;Jmp
  241.          move.l a0,(a1)+                        ;to NOP
  242.         next d1
  243.  
  244.         lea mulib_Internals(a4),a1
  245.         move.l a4,a6
  246.         lea Init851(pc),a0                      ;now initialize MMU specific stuff
  247.         cmp.b #mutype_68851,d0
  248.         beq.s .initme
  249.  
  250.         lea Init030(pc),a0
  251.         cmp.b #mutype_68030,d0
  252.         beq.s .initme
  253.  
  254.         lea Init040(pc),a0
  255.         cmp.b #mutype_68040,d0
  256.         beq.s .initme
  257.  
  258.         lea Init060(pc),a0
  259.         cmp.b #mutype_68060,d0
  260.         bne.s .nommu                            ;no known MMU here!
  261. .initme:
  262.         jsr (a0)                                ;jump to the init vector of this MMU
  263.         tst.l d0                                ;did work?
  264.         beq .alertnommu
  265. .nommu:
  266.         move.l mulib_SysBase(a4),a6
  267.         jsr CacheClearU(a6)                     ;Flush the initialized vectors
  268.  
  269.         move.l a4,a6
  270.  
  271.         lea mulib_MMUConfig(a4),a0
  272.         jsr mulib_ReadConfig(a6)                ;read MMU configuration, keep it for later
  273.  
  274.         moveq #-1,d0
  275.         move.l d0,mulib_RootMask(a4)
  276.  
  277.         lea mulib_MMUConfig(a4),a0
  278.         jsr mulib_SetLibrary(a6)
  279.  
  280.         bsr SetupMasks
  281.  
  282.         bsr AllocContext                        ;allocate a context structure for the global stuff
  283.         move.l d0,mulib_DefaultContext(a4)      ;build default context
  284.         beq.s .quitpool
  285.  
  286.         move.l d0,a0
  287.         bsr BuildDefaultTable                   ;define default mapping
  288.         tst.l d0
  289.         beq.s .quitpool                         ;failure
  290.  
  291.         lea mulib_MMUConfig(a4),a1
  292.         move.l mulib_DefaultContext(a4),a0
  293.         bsr ParseMMUTable                       ;scan the MMU table
  294.         tst.l d0
  295.         beq.s .quitpool
  296.  
  297.         lea mulib_MMUConfig(a4),a1
  298.         move.l mulib_DefaultContext(a4),a0
  299.         jsr mulib_ParseTT(a6)                   ;scan the transparent translation
  300.         tst.l d0
  301.         beq.s .quitpool
  302.  
  303.         move.l mulib_DefaultContext(a4),a0      ;get again this context
  304.         bsr SetGlobal                           ;make this global
  305.  
  306.         move.l mulib_DefaultContext(a4),a0
  307.         ;bsr BuildMMUTable                       ;build the table for this context
  308.         ;beq.s .quitpool
  309.  
  310.         move.l mulib_DefaultContext(a4),a1
  311.         lea mulib_ContextList(a4),a0
  312.         AddHead                                 ;add this at the start of the list
  313.  
  314.         bra .exit                               ;initialization done
  315. .alertnommu:                                    ;no need to release the
  316.         pea AN_MMUInit                          ;context. Done automatically
  317.         bsr MUAlert
  318.  
  319. .quitpool:
  320.         move.l mulib_ContextPool(a4),a0
  321.         bsr MuDeletePool
  322.         ;bra.s .closeutility
  323.  
  324. .nomemory:
  325.         ;pea AN_NoPoolMem
  326.         ;bsr MUAlert
  327.  
  328. .closeutility:
  329.         move.l mulib_SysBase(a4),a6
  330.         move.l mulib_UtilityBase(a4),a1
  331.         jsr CloseLibrary(a6)
  332.         clr.l mulib_UtilityBase(a4)
  333.         bra.s .overu
  334. .noutility:
  335.         pea AN_NoUtility
  336.         bsr MUAlert
  337. .overu:
  338.         move.l mulib_SysBase(a4),a6
  339.         move.l mulib_ExpansionBase(a4),a1
  340.         jsr CloseLibrary(a6)
  341.         clr.l mulib_ExpansionBase(a4)
  342.         bra.s .overe
  343.  
  344. .noexpansion:
  345.         pea AN_NoExpansion
  346.         bsr MUAlert
  347. .overe:
  348.         move.l mulib_SysBase(a4),a6
  349.         move.l mulib_040Base(a4),d0
  350.         beq.s .no040
  351.         move.l d0,a1
  352.         jsr CloseLibrary(a6)
  353. .no040:
  354.         move.l mulib_060Base(a4),d0
  355.         beq.s .no060
  356.         move.l d0,a1
  357.         jsr CloseLibrary(a6)
  358. .no060:
  359.  
  360. .failure:                                       ;in case of a failure,
  361.                                                 ;we've to cleanup ourselves
  362.         move.l mulib_SysBase(a4),a6
  363.         move.l a4,a1
  364.         moveq #0,d0
  365.         moveq #0,d1
  366.         move.w mulib_negsize(a4),d0
  367.         move.w mulib_possize(a4),d1
  368.         sub.l d0,a1                             ;*Mem
  369.         add.l d1,d0                             ;length
  370.         jsr FreeMem(a6)                         ;release memory
  371.  
  372.         sub.l a4,a4                             ;tough luck
  373. .exit:
  374.         move.l a4,d0
  375.         loadregs
  376.         rts
  377. NOP:
  378.         moveq #0,d0
  379.         rts
  380. ;ENDFOLD
  381. ;FOLD OpenMULib
  382. ;*************************************************
  383. ;** OpenMULib                                   **
  384. ;** Open the MMU library                        **
  385. ;*************************************************
  386. OpenMULib:
  387.         bclr #lib_delexp,mulib_flags(a6)        ;clear the delayed expunge flag
  388.         addq.w #1,mulib_opencnt(a6)             ;increment the open counter
  389.         move.l a6,d0                            ;that's it
  390.         rts
  391. ;ENDFOLD
  392. ;FOLD CloseMULib
  393. ;*************************************************
  394. ;** CloseMULib                                  **
  395. ;** Close the MMU library again                 **
  396. ;*************************************************
  397. CloseMULib:
  398.         tst.w mulib_opencnt(a6)
  399.         beq.s .ignore
  400.         subq.w #1,mulib_opencnt(a6)             ;Decrement open counter
  401.         btst #lib_delexp,mulib_flags(a6)        ;Delayed expunge active ?
  402.         bne.s ExpungeMULib
  403. .ignore:
  404.         moveq #0,d0                             ;do not quit
  405.         rts
  406. ;ENDFOLD
  407. ;FOLD ExpungeMULib
  408. ;*************************************************
  409. ;** ExpungeMULib                                **
  410. ;** Remove the MMU library from memory, if      **
  411. ;** possible                                    **
  412. ;*************************************************
  413. ExpungeMULib:
  414.         bset #lib_delexp,mulib_flags(a6)        ;delay at least
  415.         moveq #0,d0                             ;do not flush
  416.         tst.w mulib_opencnt(a6)                 ;still in use?
  417.         bne .exit
  418.         btstm mmuf1_contextopen,mulib_flags1(a6)        ;still an open context?
  419.         beq.s .flush
  420.                                                 ;here yes. Something went extremly wrong
  421.         pea AN_ContextOpen
  422.         bsr MUAlert                             ;Create a guru
  423.         moveq #0,d0                             ;do not quit
  424.         bra .exit
  425. .flush:
  426.         saveregs a4
  427.         move.l a6,a4
  428.                                                 ;restore the vector base
  429.  
  430.         move.l a6,a1
  431.         Remove                                  ;Remove the library from the system list
  432.  
  433.         move.l mulib_DefaultContext(a6),a1
  434.         Remove                                  ;Remove this Context
  435.  
  436.         lea mulib_MMUConfig(a6),a0
  437.         jsr mulib_WriteConfig(a6)               ;restore original MMU data
  438.  
  439.         move.l mulib_DefaultContext(a6),a0
  440.         bclrm ctxf_active,ctx_Flags(a0)         ;deactivate the context by
  441.                                                 ;brute force. The MMU has been reloaded by the call above
  442.         bsr FreeContext                         ;release it and the tables
  443.  
  444.  
  445.         move.l mulib_ContextPool(a6),a0
  446.         bsr MUDeletePool                        ;release the memory pool. Releases the context as well and the context mapping
  447.  
  448.         move.l mulib_SysBase(a6),a6
  449.  
  450.         move.l mulib_UtilityBase(a4),d0
  451.         beq.s .noutility
  452.         move.l d0,a1
  453.         jsr CloseLibrary(a6)
  454. .noutility:
  455.         move.l mulib_ExpansionBase(a4),d0
  456.         beq.s .noexpansion
  457.         move.l d0,a1
  458.         jsr CloseLibrary(a6)
  459. .noexpansion:
  460.         move.l mulib_060Base(a4),d0
  461.         beq.s .no60
  462.         move.l d0,a1
  463.         jsr CloseLibrary(a6)
  464. .no60:
  465.         move.l mulib_040Base(a4),d0
  466.         beq.s .no40
  467.         move.l d0,a1
  468.         jsr CloseLibrary(a6)
  469. .no40:
  470.  
  471.         move.l mulib_Segment(a4),-(a7)          ;Saveback the segment
  472.         move.l a4,a1                            ;->Base Mem
  473.         moveq #0,d0
  474.         moveq #0,d1
  475.         move.w mulib_negsize(a1),d0             ;NegSize->d0
  476.         move.w mulib_possize(a1),d1             ;Possize->d1
  477.         sub.l d0,a1                             ;*Mem
  478.         add.l d1,d0                             ;mem total
  479.         jsr FreeMem(a6)                         ;release
  480.  
  481.         move.l (a7)+,d0                         ;restore segment
  482.         loadregs
  483. .exit:
  484.         rts
  485. ;ENDFOLD
  486.  
  487. ;FOLD SetupMasks
  488. ;*************************************************
  489. ;** SetupMasks                                  **
  490. ;** use the data filled in by the MMU setup     **
  491. ;** codes to build all the mask and bit         **
  492. ;** lookup tables we need                       **
  493. ;*************************************************
  494. SetupMasks:
  495.         saveregs d2-d5/a2-a5
  496.  
  497.         moveq #-1,d1
  498.         moveq #1,d2
  499.         move.l #4,mulib_IndirectAlign(a6)       ;this is fixed
  500.         lea mulib_LevelAAlign(a6),a5
  501.         lea mulib_LevelAMask(a6),a4
  502.         lea mulib_LevelATableSz-4(a6),a3
  503.         lea mulib_LevelAPos-1(a6),a2
  504.         lea mulib_LevelASize-4(a6),a1
  505.         lea mulib_LevelABits-1(a6),a0
  506.         moveq #0,d3
  507.         do
  508.          move.b (a0)+,d0                ;bits for this level
  509.          beq.s .noshift
  510.          ror.l d0,d2                    ;calculate size of the pages at this level
  511. .noshift:
  512.          move.b d3,(a2)+                ;the starting bit position within the address at this level
  513.          moveq #0,d4
  514.          add.b d0,d3                    ;add up the bits
  515.          move.l (a5)+,d5                ;read the alignment restrictions
  516.          bset d0,d4                     ;the number of entries at this level
  517.          neg.l d5                       ;calculate a mask from that
  518.          move.l d2,d0                   ;keep the page size
  519.          move.l d5,(a4)+                ;enter the mask
  520.          and.b #$fe,d0                  ;bit 0 might not yet have been shifted out
  521.          move.l d4,(a3)+                ;insert the number of entries for a table at this level
  522.          addq.w #1,d1                   ;increment the counter
  523.          move.l d0,(a1)+                ;insert the page size
  524.          cmp.w #4,d1                    ;until done
  525.         while.s ls
  526.  
  527.         loadregs
  528.         rts
  529. ;ENDFOLD
  530.  
  531. ;** Function entries
  532.  
  533. ;FOLD GetMapping
  534. ;*************************************************
  535. ;** GetMapping                                  **
  536. ;** get for the ctx *a0 or the default ctx      **
  537. ;** if *a0==NULL the mapping. Lock the context  **
  538. ;*************************************************
  539. GetMapping:
  540.         move.l a0,d0
  541.         bne.s .nodefault
  542.         move.l mulib_DefaultContext(a6),a0
  543. .nodefault:
  544.         bsr LockContext
  545.  
  546.         lea ctx_Mapping(a0),a0
  547.         move.l a0,d0
  548.         rts
  549. ;ENDFOLD
  550. ;FOLD ReleaseMapping
  551. ;*************************************************
  552. ;** ReleaseMapping                              **
  553. ;** release the mapping of context *a0          **
  554. ;** or the default context if NULL              **
  555. ;*************************************************
  556. ReleaseMapping:
  557.         move.l a0,d0
  558.         bne.s .nodefault
  559.         move.l mulib_DefaultContext(a6),a0
  560. .nodefault:
  561.         bsr UnlockContext
  562.         rts
  563. ;ENDFOLD
  564. ;FOLD GetPageSize
  565. ;*************************************************
  566. ;** GetPageSize                                 **
  567. ;** Return the page size of the MMU             **
  568. ;*************************************************
  569. GetPageSize:
  570.         move.l mulib_PageSize(a6),d0
  571.         rts
  572. ;ENDFOLD
  573. ;FOLD GetMMUType
  574. ;*************************************************
  575. ;** GetMMUType                                  **
  576. ;** return the type of the MMU installed        **
  577. ;*************************************************
  578. GetMMUType:
  579.         moveq #0,d0
  580.         move.b mulib_MMUType(a6),d0
  581.         rts
  582. ;ENDFOLD
  583. ;FOLD GetMMUConfig
  584. ;*************************************************
  585. ;** GetMMUConfig                                **
  586. ;** read the MMU hardware registers.            **
  587. ;** should be handled with care                 **
  588. ;*************************************************
  589. GetMMUConfig:
  590.         move.l #mcf_len,d0
  591.         bsr AllocContextMem             ;get memory for the configuration
  592.         beq.s .exit
  593.  
  594.         move.l d0,-(a7)
  595.         move.l d0,a0
  596.         jsr mulib_ReadConfig(a6)        ;fill in the MMU configuration
  597.         move.l (a7)+,d0
  598. .exit:
  599.         rts
  600. ;ENDFOLD
  601. ;FOLD ReleaseMMUConfig
  602. ;*************************************************
  603. ;** ReleaseMMUConfig                            **
  604. ;** release the MMU information                 **
  605. ;*************************************************
  606. ReleaseMMUConfig:
  607.         move.l a1,d0
  608.         beq.s .noconfig
  609.         bsr FreeContextMem
  610. .noconfig:
  611.         rts
  612. ;ENDFOLD
  613.  
  614.  
  615.  
  616.         section main_data,data
  617. ;FOLD Strings
  618.         xdef MMUName
  619. MMUName:        dc.b "mmu.library",0
  620. UtilityName:    dc.b "utility.library",0
  621. ExpansionName:  dc.b "expansion.library",0
  622. MC68040Name:    dc.b "68040.library",0
  623. MC68060Name:    dc.b "68060.library",0
  624.                 dc.b "$VER: "
  625. IDString:       dc.b "mmu "
  626.                 TextVersion
  627.                 dc.b " "
  628.                 TextDate
  629.                 dc.b " (c) 1998 The MMU.lib development group, THOR",$0a,$0d,0
  630.  
  631. ;ENDFOLD
  632. ;
  633.